<script setup>
import { ref, toRefs, reactive, onBeforeMount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import StringOrNumber from '../components/StringOrNumber.vue';
import CreateOrEditFrame from '../components/CreateOrEditFrame.vue';
import { listHandler } from '../../api/Generic'
import { deleteTableRow, object2List, list2Object  } from '../../utils/utils';
import Table from '../components/Table.vue';
import DialogYaml from '../components/DialogYaml.vue'
import { obj2Yaml } from '../../utils/utils';
import { createServiceHandler as createHandler, updateServiceHandler as updateHandler } from '../../api/service.js'
import { useRouter } from 'vue-router'
const router = useRouter()
const props = defineProps({
  method: {
    type: String,
    default: 'Create'
  },
  item: {
    type: Object
  }
})
const data = reactive({
  clusterId: '',
  namespace: '',
  item: {// service数据结构定义
    apiVersion: 'v1',
    kind: 'Service',
    metadata: {
      name: '',
      namespace: '',
      labels: {},
      annotations: {},
    },
    spec: {
      ports: [],
      selector: {},
      type: 'ClusterIP'
    }
  },
  options: {
    proxyResourceTypeSelected: '',
    proxyResourceTypes: [
      {
        label: 'Deployment',
        value: 'Deployment'
      },
      {
        label: 'StatefulSet',
        value: 'StatefulSet'
      },
      {
        label: 'DaemonSet',
        value: 'DaemonSet'
      },
      {
        label: '外部域名',
        value: 'ExternalName'
      },
      // {
      //   label: '外部均衡',
      //   value: 'LoadBalance'
      // },
    ],
    items: [], // 请求控制器接口返回的数据
    item: undefined, // 初始值设置为undefined或者'' 解决el-select placeholder不显示bug
    serviceTypes: [
      {
        label: "ClusterIP",
        value: "ClusterIP"
      },
      {
        label: "NodePort",
        value: "NodePort"
      },
      {
        label: "LoadBalancer",
        value: "LoadBalancer"
      },
      // {
      //   label: "ExternalName",
      //   value: "ExternalName"
      // }
    ],
    labelList: [],
    annotationList: [],
    podLabelList: [],
    rules:{
      name: [
        {required: true, message: 'service名称必须有', trigger:'blur'}
      ],
      externalName: [
        {required: true, message: '请输入代理的域名', trigger:'blur'},
        { pattern: '^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$', message: "请检查域名", trigger: "blur" }

      ]
    }
  }
})
const itemRef = ref()
const activeName = ref('basic')
const labelConfig = ref('labels')
const yamlContent = ref('')
const showDetail = ref(false)

const submitRollback = (msg) => {
  ElMessageBox.confirm(
    msg,
    '执行结果',
    {
      confirmButtonText: '查看列表',
      cancelButtonText: '返回',
      type: 'success',
      draggable: true,
    }
  ).then(() => {
    // 跳转/service/list
    router.replace({
      path: '/service/list',
      query: {
        clusterId: data.clusterId,
        namespace: data.namespace
      }
    })
  }).catch(() => {
    return
  })
}
const submitHandler = (tag) => {
  data.item.metadata.labels = list2Object(data.options.labelList)
  data.item.metadata.annotations = list2Object(data.options.annotationList)
  if(data.item.spec.type != 'ExternalName') {
    data.item.spec.selector = list2Object(data.options.podLabelList)
  }
  if(tag == 'yaml') { // json转yaml
    const yamlData = obj2Yaml(data.item)
    yamlContent.value = yamlData
    showDetail.value = true
  } else {
    const postData = {
      clusterId: data.clusterId,
      namespace: data.namespace,
      item: data.item
    }
    if (props.method != 'Update') {
      createHandler(postData).then((response) => {
        submitRollback(response.data.message)
      })
    } else {
      updateHandler(postData).then((response) => {
        console.log(props.method)
        submitRollback(response.data.message)
      })
    }
  }
}
const submit = (tag) => {
  itemRef.value.validate((valid) => {
    if(!valid){
      ElMessage({
        message: '请完善表单',
        type: "warning"
      })
    }else {
      submitHandler(tag)
    }
  })
  

}
const namespaceChangedHandler = (clusterId, namespace) => {
  console.log('service namespaceChangedHandler', clusterId, namespace)
  data.clusterId = clusterId
  data.namespace = namespace
  data.item.metadata.namespace = namespace
  // 刷新资源列表
  if(data.options.proxyResourceTypeSelected != 'ExternalName' && data.options.proxyResourceTypeSelected != ''){
    getResourceList()
  }

}

const getResourceList = async () => {
  console.log("获取资源列表：", data.clusterId, data.namespace, data.options.proxyResourceTypeSelected)
  await listHandler(data.clusterId, data.namespace, data.options.proxyResourceTypeSelected).then((res)=>{
    console.log("获取到的资源列表:", res.data.data.items)
    data.options.item = undefined // 产生变化时清空items
    data.options.items = res.data.data.items
  })
}


const proxyResourceTypeChanged = (val) => {
  console.log("选择代理的类型是:", val)
  if (val == 'ExternalName'){
    data.options.item = undefined // 切换到ExternalName时清空items
    const serviceSpec = {
      type: 'ExternalName',
      externalName: ''
    }
    data.item.spec = serviceSpec
    return
  } else {
    delete data.item.spec.externalName
    data.item.spec.type = 'ClusterIP'
    getResourceList()
  }


}
const headlessServiceChanged = (val) => {
  console.log("headlessService:", val)
  if (!val){
    delete data.item.spec.clusterIP
  }
}
const sessionAffinityChanged = (val) => {
  console.log("会话保持切换处理:", val)
  if(val=='None'){ // 关闭会话保持
    data.item.spec.sessionAffinity = 'None'
    delete data.item.spec.sessionAffinityConfig
  }else{ // 开启会话保持
    data.item.spec.sessionAffinity = 'clientIP'
    data.item.spec.sessionAffinityConfig = {
      clientIP: {
        timeoutSeconds: 3600
      }
    }
  }
}

// 选择的资源产生变化
const proxyResourceChanged = () => {
  console.log("选择的资源产生变化:", data.options.item)
  data.item.metadata.name = data.options.item.metadata.name
  const containers = data.options.item.spec.template.spec.containers
  
  data.item.spec.ports = [] // 切换清空
  for(let c=0;c<containers.length;c++){
    const container = containers[c]
    const containerPorts = container.ports
    if(!containerPorts){continue} //如果没用ports字段
    for(let p=0;p<containerPorts.length;p++){
      const containerPort = containerPorts[p]
      console.log('containerPort的值:', containerPort)
      const servicePort = {
        name: containerPort.name,
        port: containerPort.containerPort,
        protocol: containerPort.protocol,
        targetPort: containerPort.containerPort
      }
      data.item.spec.ports.push(servicePort)
    }
  }
  // 处理标签配置
  data.options.labelList = object2List(data.options.item.metadata.labels)
  data.options.annotationList = object2List(data.options.item.metadata.annotations)
  data.options.podLabelList = object2List(data.options.item.spec.template.metadata.labels)
}

// 添加端口
const addPort = () => {
  if(data.item.spec.ports == null || data.item.spec.ports == undefined){
    data.item.spec.ports = []
  }
  const port = {
    port: undefined,
    targetPort: undefined,
    protocol: 'TCP',
    name: ''
  }
  data.item.spec.ports.unshift(port)
}
const serviceTypeChanged= () => {
  if(data.item.spec.type == 'ClusterIP'){
    console.log('删除nodePort配置')
    data.item.spec.ports.forEach(port => {
      delete port.nodePort
    });
  }
}
onBeforeMount(() => {
  if(props.method != 'Create'){
    data.item = JSON.parse(JSON.stringify(props.item))
    data.options.labelList = object2List(data.item.metadata.labels)
    data.options.annotationList = object2List(data.item.metadata.annotations)
    if (data.item.spec.type != 'ExternalName'){
      data.options.podLabelList = object2List(data.item.spec.selector)
    }
  }
})

const { options, item, clusterId, namespace } = toRefs(data)
</script>

<template>
  <CreateOrEditFrame
  :namespace-readonly="props.method=='Update'"
  :cluster-readonly="props.method=='Update'"
  @namespace-chanaged-rollback="namespaceChangedHandler"
  >
  <!-- 头部插入内容 -->
    <template #header>
      <!-- 选择控制器类型 -->
      <el-select
      style="margin-left: 10px; width: 180px;"
      v-if="props.method == 'Create'"
      v-model="options.proxyResourceTypeSelected"
      placeholder="选择创建代理的类型"
      @change="proxyResourceTypeChanged"
      >
        <el-option
        v-for="t in options.proxyResourceTypes"
        :key="t.value"
        :label="t.label"
        :value="t.value"
        >
        </el-option>
      </el-select>
      <!-- 选择资源名称 -->
      <el-select
      style="margin-left: 10px; width: 180px;"
      v-if="props.method == 'Create' && data.options.proxyResourceTypeSelected != 'ExternalName'"
      v-model="options.item"
      value-key="metadata.name"
      placeholder="选择代理的资源"
      @change="proxyResourceChanged"
      >
        <el-option
        v-for="t in options.items"
        :key="t.metadata.name"
        :label="t.metadata.name"
        :value="t"
        >
        </el-option>
      </el-select>
    </template>
    <template #main>
      <el-form :model="item"
      ref="itemRef"
      >
        <el-tabs v-model="activeName" class="demo-tabs">
          <el-tab-pane label="基本配置" name="basic" style="height:240px">
            <el-row :gutter="20">
              <el-col :span="6">
                <el-form-item :rules="options.rules.name" label="Service名称" prop="metadata.name" required>
                  <el-input :disabled="props.method =='Update'" v-model="item.metadata.name" style="margin-left: 10px; width: 180px;"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="6" v-show="options.proxyResourceTypeSelected != 'ExternalName'">
                <el-form-item label="Service类型" prop="">
                  <el-select
                  style="margin-left: 10px; width: 180px;"
                  v-model="item.spec.type"
                  value-key="metadata.name"
                  placeholder="选择Service类型"
                  @change="serviceTypeChanged"
                  >
                    <el-option
                    v-for="t in options.serviceTypes"
                    :key="t.value"
                    :label="t.label"
                    :value="t.value"
                    >
                    </el-option>
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="2" v-show="item.spec.type != 'ExternalName' && item.spec.type == 'ClusterIP'">
                <el-form-item label="无头服务" prop="" title="一般配合statefulset使用">
                  <el-switch v-model="item.spec.clusterIP" active-value="None" @change="headlessServiceChanged"></el-switch>
                </el-form-item>
              </el-col>
              <el-col :span="3" v-show="item.spec.type != 'ExternalName'">
                <el-form-item label="会话保持" prop="">
                  <el-switch v-model="item.spec.sessionAffinity" active-value="clientIP" inactive-value="None" @change="sessionAffinityChanged"></el-switch>
                </el-form-item>
              </el-col>
              <el-col :span="4" v-if="item.spec.type != 'ExternalName' && item.spec.sessionAffinity == 'clientIP'">
                <el-form-item label="会话保持时间" prop="">
                  <el-input-number :min="1" v-model="item.spec.sessionAffinityConfig.clientIP.timeoutSeconds" :controls="false"></el-input-number>
                </el-form-item>
              </el-col>
              <el-col :span="6" v-if="item.spec.type=='ExternalName'">
                <el-form-item
                label="请输入代理的目标域名"
                :title="'集群内coreDNS会将'+item.metadata.name+'.'+item.metadata.namespace+'.svc.cluster.local'+' CNAME的方式到:'+item.spec.externalName"
                prop="spec.externalName"
                :rules="options.rules.externalName" required>
                  <el-input v-model="item.spec.externalName" style="margin-left: 10px; width: 180px;"></el-input>
                </el-form-item>
              </el-col>
            </el-row>
          </el-tab-pane>



          <el-tab-pane label="端口配置" name="ports" v-if="options.proxyResourceTypeSelected != 'ExternalName'">
            <el-form-item style="width:100%">
              <el-table :data="item.spec.ports" border style="height: 240px;">
                <el-table-column label="service名称" width="240" align="center">
                  <template #default="scope">
                    <el-input title="对应ports.name" v-model.trim="scope.row.name" placeholder="service端口名称"></el-input>
                  </template>
                </el-table-column>

                <el-table-column label="service端口" width="180" align="center">
                  <template #default="scope">
                    <el-form-item	label="" title="对应ports.port" :prop="('spec.ports.' + scope.$index + '.port')" required>
                      <el-input-number :controls="false" :min="1" :max="65535" v-model="scope.row.port" placeholder="数字:1~65535"></el-input-number>
                    </el-form-item>
                  </template>
                </el-table-column>

                <el-table-column label="程序端口" width="180" align="center">
                  <template #default="scope">
                    <StringOrNumber title="对应后端程序端口targetPort" :key="item.spec.ports" input-width="100%" v-model:data="scope.row.targetPort" placeholder="后端程序端口或名称"></StringOrNumber>
                  </template>
                </el-table-column>
                
                <el-table-column label="协议" width="140" align="center">
                  <template #default="scope">
                    <el-select title="代理协议" v-model="scope.row.protocol" placeholder="协议">
                      <el-option v-for="p in ['TCP','UDP','SCTP']" :key="p" :label="p" :value="p">
                      </el-option>
                    </el-select>
                  </template>
                </el-table-column>

                <el-table-column label="NodePort" width="180" align="center">
                  <template #default="scope">
                    <el-input-number title="对应宿主机端口 由apiserver: --service-node-port-range字段决定"
                    style="width:100%" :controls="false" :disabled="item.spec.type != 'NodePort' && item.spec.type != 'LoadBalancer'"
                    :min="1" :max="65535" v-model="scope.row.nodePort" placeholder="NodePort"></el-input-number>
                  </template>
                </el-table-column>

                <el-table-column label="操作" align="center">
                  <template #header>
                    <el-button link type="primary" @click="addPort()">添加</el-button>
                  </template>
                  <template #default="scope">
                    <el-button link type="warning" @click="deleteTableRow(item.spec.ports, scope.$index)">删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </el-form-item>
          </el-tab-pane>

          <el-tab-pane label="注释及标签" name="labels">
            <el-tabs v-model="labelConfig" tabPosition="left">
              <el-tab-pane label="service标签配置" name="labels">
                <Table :list="options.labelList"></Table>
              </el-tab-pane>
              <el-tab-pane label="service注解配置" name="annos">
                <Table :list="options.annotationList"></Table>
              </el-tab-pane>
              <el-tab-pane label="代理的Pod标签" name="pod-labels" v-if="item.spec.type != 'ExternalName'">
                <Table :list="options.podLabelList"></Table>
              </el-tab-pane>
            </el-tabs>
          </el-tab-pane>
        </el-tabs>
        <span style="display: block;margin-top: 30px;" class="span-button">
          <el-button @click="submit('yaml')">yaml</el-button>
          <el-button type="primary" @click="submit()">{{ props.method=="Update"?"更新":"创建" }}</el-button>
        </span>
      </el-form>
    </template>
  </CreateOrEditFrame>
  <DialogYaml
  :cluster-id="clusterId"
  :namespace="namespace"
  :yaml-content="yamlContent"
  :show-dialog="showDetail"
  @close-dialog-handler="(val) => { showDetail = val }"
  >
  </DialogYaml>
</template>

<style scoped>
</style>
